﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using ESpace;

namespace CalcCalorie
{
    public partial class FormAddDish : Form
    {
        #region *** Переменные *********************************************************************

        public Dish ReturnDish
        {
            get
            {
                return ((Dish)Gl.DB.Items[sInd1].Items[sInd2]).Clone();
            }
        }

        public int mass = 100;

        bool bOk = false;
        bool bAdd = false;

        int sInd1
        {
            get { return lv1.SelectedIndices.Count > 0 ? lv1.SelectedIndices[0] : -1; }
            set
            {
                lv1.SelectedIndices.Clear();
                if (value != -1)
                {
                    this.lv1.Focus();
                    this.lv1.Items[value].Selected = true;
                    btnAddDish.Enabled = !bAdd;
                }
                else btnAddDish.Enabled = false;
            }
        }

        int sInd2
        {
            get { return lv2.SelectedIndices.Count > 0 ? lv2.SelectedIndices[0] : -1; }
            set
            {
                lv2.SelectedIndices.Clear();
                if (value != -1)
                {
                    this.lv2.Focus();
                    this.lv2.Items[value].Selected = true;
                }
            }
        }

        string editString; // редактируемая строка. Для проверки уникальности при редактировании чего-либо

        bool bRefill = false;

        FormFind frmFind = new FormFind();

        #endregion *** Переменные ********************************************************************

        public FormAddDish()
        {
            InitializeComponent();
        }

        public bool ShowDialog(bool bAdd)
        {
            this.bAdd = bAdd;

            bOk = false;

            lv2.MultiSelect = !bAdd;

            ShowDialog();

            return bOk;
        }

        private void FormAddDish_Shown(object sender, EventArgs e)
        {
            lv1.BackColor = bAdd ? SystemColors.Control : SystemColors.Window;
            lv2.BackColor = bAdd ? SystemColors.Control : SystemColors.Window;

            ReFillTpLb();

            btnAddType.Enabled = !bAdd;
            btnAddDish.Enabled = false;
        }

        private void FormAddDish_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.F && e.Control)
                btnFind_Click(null, null);
        }

        private void lv_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F && e.Control)
                btnFind_Click(null, null);
        }

        #region *** Прочие Фии *********************************************************************

        void ReFillTpLb()
        {
            lv1.Items.Clear();
            int lastInd = sInd1;
            for (int i = 0; i < Gl.DB.Items.Count; i++)
            {
                lv1.Items.Add(Gl.DB.Items[i].Name, 0);
            }
        }

        void ReFillDishLb()
        {
            int lastInd = sInd2;

            lv2.Items.Clear();
            lblCc.Text = "";
            if (sInd1 == -1) return;

            List<DBItem> dl = Gl.DB.Items[sInd1].Items;
            string tpName = Gl.DB.Items[sInd1].Name;
            for (int i = 0; i < dl.Count; i++)
            {
                ListViewItem itm = new ListViewItem(dl[i].Name, 2);
                itm.SubItems.Add(Math.Round(((Dish)dl[i]).Cc100, 1).ToString());
                lv2.Items.Add(itm);
            }

        }

        void SortAndReFillAndSave(String SelectedType, String SelectedDish)
        {
            btnAddDish.Enabled = false;

            bRefill = true;

            Gl.DB.Items.Sort();
            for (int i = 0; i < Gl.DB.Items.Count; i++)
                Gl.DB.Items[i].Items.Sort();

            // заполняем лист каталогов
            ReFillTpLb();
            // находим текущий каталог
            if (SelectedType != "")
            {
                for (int t = 0; t < Gl.DB.Items.Count; t++)
                    if (Gl.DB.Items[t].Name == SelectedType)
                    {
                        sInd1 = t;
                        break;
                    }
            }

            // заполняем лист блюд
            ReFillDishLb();
            // находим текущее блюдо
            if (sInd1 != -1 && SelectedDish != "")
            {
                for (int d = 0; d < Gl.DB.Items[sInd1].Items.Count; d++)
                {
                    if (Gl.DB.Items[sInd1].Items[d].Name == SelectedDish)
                    {
                        sInd2 = d;
                        lblCc.Text = SelectedDish.ToString();
                        break;
                    }
                }
            }
            bRefill = false;

            Gl.SaveDB(Gl.DB, Gl.fPathDB);
        }

        // проверяем на дубликаты имя каталога
        string CheckType(string RetVal)
        {
            string s = RetVal.Trim();
            if (s == "") return "Название каталога не может быть пустым";
            for (int i = 0; i < Gl.DB.Items.Count; i++)
                if (Gl.DB.Items[i].Name == s && editString != s)
                    return "Каталог с таким именем уже существует";

            return "";
        }

        #endregion *** Прочие Фии ********************************************************************

        #region *** События lv1 ********************************************************************

        private void lv1_SelectedItemChanged(object Sender, EventArgs e)
        {
            if (bRefill) return;

            if (sInd1 == -1)
            {
                btnAddDish.Enabled = false;
                ReFillDishLb();
                return;
            }

            ReFillDishLb();
            if (!bAdd) btnAddDish.Enabled = true;
        }

        // редактирование каталога
        private void lv1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            FormEditValue frmEd = new FormEditValue();
            editString = Gl.DB.Items[sInd1].Name;
            if (frmEd.ShowDialog("Каталог", editString, true, new FormEditValue.CheckRetValDelegate(CheckType)))
            {
                string selDish = ""; if (sInd2 != -1) selDish = Gl.DB.Items[sInd1].Items[sInd2].Name;
                Gl.DB.Items[sInd1].Name = frmEd.RetVal.Trim();
                SortAndReFillAndSave(Gl.DB.Items[sInd1].Name, selDish);
            }
            frmEd.Dispose();
        }

        #endregion *** События lv1 ********************************************************************

        #region *** События lv2 ********************************************************************

        private void lv2_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (bRefill) return;
            if (sInd2 == -1) return;

            lblCc.Text = Gl.DB.Items[sInd1].Items[sInd2].ToString();
        }

        // редактирование массы блюда или самого блюда
        private void lv2_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (sInd2 == -1) return;

            if (bAdd)
            {
                FormEditValue frmEd = new FormEditValue();
                if (frmEd.ShowDialog("Масса блюда", "", false, new FormEditValue.CheckRetValDelegate(Gl.CheckMass)))
                {
                    bOk = true;
                    mass = Convert.ToInt32(frmEd.RetVal.Trim());
                    Close();
                }
                frmEd.Dispose();
            }
            else mBtnEditDish_Click(null, null);
        }

        #endregion *** События lv2 ********************************************************************

        #region *** события меню lv1 ***************************************************************

        private void mBtnAddType_Click(object sender, EventArgs e)
        {
            btnAddType_Click(null, null);
        }

        // редактирование наименования каталога
        private void mBtnEditType_Click(object sender, EventArgs e)
        {
            lv1_MouseDoubleClick(null, null);
        }

        private void menuDishType_Opening(object sender, CancelEventArgs e)
        {
            if (bAdd) { e.Cancel = true; return; }
            bool vis = sInd1 != -1;
            toolStripSeparator4.Visible = vis;
            mBtnEditType.Visible = vis;
            mBtnDelType.Visible = vis;
        }

        private void mBtnDelType_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Действительно удалить каталог (все блюда в каталоге будут удалены)", "Удаление", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                Gl.DB.Items.RemoveAt(sInd1);
                SortAndReFillAndSave("", "");
            }
        }

        private void mBtnImport_Click(object sender, EventArgs e)
        {
            /*opn.FileName = ""; // Default file name
            opn.DefaultExt = ".csv"; // Default file extension
            opn.Filter = "CSV|*.csv"; // Filter files by extension
            if (opn.ShowDialog() == DialogResult.OK)
            {
                List<String> ExeptDishName = new List<string>(); // блюда, которые не были добавлены

                String[] sl = File.ReadAllLines(opn.FileName,Encoding.Default);
                try
                {
                    Dish addD = new Dish("");
                    for (int i = 0; i < sl.Length; i++)
                    {
                        if (sl[i].Length == 0) continue; // строка пуста
                        if (sl[i][0] == ';') continue; // строка пуста
                        String[] s = sl[i].Split(';');
                        Dish d = new Dish(s[0], Convert.ToDouble(s[1]), Convert.ToDouble(s[2]), Convert.ToDouble(s[3]), Convert.ToDouble(s[4]));
                        if (!Gl.DishIsUnic(tl, d.name, 2) || !Gl.DishIsUnic(addD, d.name, 1))
                            ExeptDishName.Add(d.name);
                        else
                            addD.dl.Add(d);
                    }

                    for (int i = 0; i < addD.dl.Count; i++)
                    {
                        SelectedType.dl.Add(addD.dl[i]);
                    }

                    if (ExeptDishName.Count > 0)
                    {
                        String s = "Следующие блюда небыли добавлены по причине дублирования имен:\r\n";
                        for (int i = 0; i < ExeptDishName.Count; i++)
                        {
                            s += ExeptDishName[i] + "\r\n";
                        }
                        MessageBox.Show(s);
                    }

                    ReFill(true, false);
                    SaveDishList();
                }
                catch
                {
                    MessageBox.Show("Не удалось импортировать данные. Проверьте правильность формата данных и попробуйте снова.");
                }
            }*/
        }

        #endregion *** события меню lv1 ***************************************************************

        #region *** события меню lv2 ***************************************************************

        private void menuDish_Opening(object sender, CancelEventArgs e)
        {
            if (bAdd || sInd1 == -1) { e.Cancel = true; return; }

            bool vis = sInd2 != -1;
            toolStripSeparator3.Visible = vis;
            mBtnEditDish.Visible = vis;
            mBtnDelDish.Visible = vis;
        }

        private void mBtnAddDish_Click(object sender, EventArgs e)
        {
            btnAddDish_Click(null, null);
        }

        // редактирование блюда в списке блюд
        private void mBtnEditDish_Click(object sender, EventArgs e)
        {
            FormEditDish frmEditDish = new FormEditDish();
            if (frmEditDish.ShowDialog((DIR)Gl.DB.Items[sInd1], sInd2))
            {
                // редактируем блюдо
                Gl.DB.Items[sInd1].Items[sInd2] = frmEditDish.ReturnDish.Clone();
                // пересохраняем лист
                SortAndReFillAndSave(Gl.DB.Items[sInd1].Name, frmEditDish.ReturnDish.Name);
            }
            frmEditDish.Dispose();
        }

        private void mBtnDelDish_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Действительно удалить? (восстановить не удасться)", "Удаление", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                int ind = sInd1;
                int ind1 = sInd2;
                Gl.DB.Items[ind].Items.RemoveAt(ind1);
                // пересохраняем лист
                SortAndReFillAndSave(Gl.DB.Items[ind].Name, "");
            }
        }

        #endregion *** события меню lv2 ***************************************************************

        #region *** Прочие события *****************************************************************

        // добавить блюдо в список блюд
        private void btnAddDish_Click(object sender, EventArgs e)
        {
            FormEditDish frmEditDish = new FormEditDish();
            if (frmEditDish.ShowDialog((DIR)Gl.DB.Items[sInd1]))
            {
                // добавляем блюдо
                Gl.DB.Items[sInd1].Items.Add(frmEditDish.ReturnDish.Clone());
                // пересохраняем лист
                SortAndReFillAndSave(Gl.DB.Items[sInd1].Name, frmEditDish.ReturnDish.Name);
            }
            frmEditDish.Dispose();
        }

        // добавление каталога
        private void btnAddType_Click(object sender, EventArgs e)
        {
            FormEditValue frmEd = new FormEditValue();
            editString = "";
            if (frmEd.ShowDialog("Каталог", "", false, new FormEditValue.CheckRetValDelegate(CheckType)))
            {
                Gl.DB.Items.Add(new DIR(frmEd.RetVal.Trim(), Gl.DB));
                SortAndReFillAndSave(frmEd.RetVal.Trim(), "");
            }
            frmEd.Dispose();
        }

        private void btnFind_Click(object sender, EventArgs e)
        {
            frmFind.DB = Gl.DB;
            frmFind.ShowDialog();
            if (frmFind.bOk)
            {
                sInd1 = frmFind.ActT;
                sInd2 = frmFind.ActD;
                lv1.TopItem = lv1.Items[sInd1];
                lv2.TopItem = lv2.Items[sInd2];

                if(bAdd) lv2_MouseDoubleClick(null, null);
            }
        }

        private void txbFlt_TextChanged(object sender, EventArgs e)
        {
            ReFillDishLb();
        }

        #endregion *** Прочие события **************************************************************

        #region *** Drag And Drop ******************************************************************

        private void lv2_ItemDrag(object sender, ItemDragEventArgs e)
        {
            lv2.DoDragDrop(lv2.SelectedItems, DragDropEffects.Move);
        }

        private void lv2_DragEnter(object sender, DragEventArgs e)
        {
            int len = e.Data.GetFormats().Length - 1;
            int i;
            for (i = 0; i <= len; i++)
            {
                if (e.Data.GetFormats()[i].Equals("System.Windows.Forms.ListView+SelectedListViewItemCollection"))
                {
                    //The data from the drag source is moved to the target.	
                    e.Effect = DragDropEffects.Move;
                }
            }

        }

        private void lv2_DragDrop(object sender, DragEventArgs e)
        {
            //Return if the items are not selected in the ListView control.
            /*if (lv2.SelectedItems.Count == 0)
            {
                return;
            }
            //Returns the location of the mouse pointer in the ListView control.
            Point cp = lv2.PointToClient(new Point(e.X, e.Y));
            //Obtain the item that is located at the specified location of the mouse pointer.
            ListViewItem dragToItem = lv2.GetItemAt(cp.X, cp.Y);
            if (dragToItem == null)
            {
                return;
            }
            //Obtain the index of the item at the mouse pointer.
            int dragIndex = dragToItem.Index;
            ListViewItem[] sel = new ListViewItem[lv2.SelectedItems.Count];
            for (int i = 0; i <= lv2.SelectedItems.Count - 1; i++)
            {
                sel[i] = lv2.SelectedItems[i];
            }
            for (int i = 0; i < sel.GetLength(0); i++)
            {
                //Obtain the ListViewItem to be dragged to the target location.
                ListViewItem dragItem = sel[i];
                int itemIndex = dragIndex;
                if (itemIndex == dragItem.Index)
                {
                    return;
                }
                if (dragItem.Index < itemIndex)
                    itemIndex++;
                else
                    itemIndex = dragIndex + i;
                //Insert the item at the mouse pointer.
                ListViewItem insertItem = (ListViewItem)dragItem.Clone();
                lv2.Items.Insert(itemIndex, insertItem);
                //Removes the item from the initial location while 
                //the item is moved to the new location.
                lv2.Items.Remove(dragItem);
            }*/
        }

        private void lv1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            //lv1.DoDragDrop(lv1.SelectedItems, DragDropEffects.Move);
        }

        private void lv1_DragEnter(object sender, DragEventArgs e)
        {
            int len = e.Data.GetFormats().Length - 1;
            int i;
            for (i = 0; i <= len; i++)
            {
                if (e.Data.GetFormats()[i].Equals("System.Windows.Forms.ListView+SelectedListViewItemCollection"))
                {
                    //The data from the drag source is moved to the target.	
                    e.Effect = DragDropEffects.Move;
                }
            }
        }

        ListViewItem DragOverItem = null;

        private void lv1_DragDrop(object sender, DragEventArgs e)
        {
            if (lv2.SelectedItems.Count == 0 || DragOverItem == null) return;

            DBItem destDir;
            // если блюдо
            if (DragOverItem.ImageIndex == 2)
            {
                destDir = Gl.DB.Items[DragOverItem.Index].Parent;
            }
            // если каталог
            else
            {
                destDir = Gl.DB.Items[DragOverItem.Index];
                DragOverItem.ImageIndex = 0;
            }

            DBItem srsDir = Gl.DB.Items[sInd1];

            if (srsDir.FullPath == destDir.FullPath)
            {
                MessageBox.Show("Нельзя перенести в тот же каталог");
                return;
            }

            string msg = "Перенести " + (lv2.SelectedItems.Count > 1 ? "выделенные блюда" : "выделенное блюдо") + " в каталог '" + destDir.Name + "'?";
            if (MessageBox.Show(msg, "Перемещение", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign) == System.Windows.Forms.DialogResult.Yes)
            {
                if (MoveItems(lv2, srsDir, destDir))
                    Gl.SaveDB(Gl.DB, Gl.fPathDB);
            }
        }

        // возвращает true, если хотябы 1 элемент перенесен
        static bool MoveItems(ListView srsLv, DBItem srsDir, DBItem destDir)
        {
            List<int> moveIndList = new List<int>();
            for (int i = 0; i < srsLv.SelectedItems.Count; i++)
                moveIndList.Add(srsLv.SelectedItems[i].Index);

            List<int> MovedIndL = srsDir.MoveItems(moveIndList, destDir, new DBItem.GetActionWithDuplDelegate(GetActionWithDupl), null);
            List<ListViewItem> removeL1 = new List<ListViewItem>();
            for (int i = 0; i < MovedIndL.Count; i++)
                removeL1.Add(srsLv.Items[MovedIndL[i]]);

            if (removeL1.Count > 0)
            {
                destDir.Items.Sort(); // сортировка в каталоге, куда перенесено
                for (int i = 0; i < removeL1.Count; i++) srsLv.Items.Remove(removeL1[i]); // удаление перенесенных из отображения

                return true;
            }
            return false;

        }

        static DBItem.ActionWithDupl GetActionWithDupl(DBItem oldItem, DBItem newItem)
        {
            if (newItem.Ext == "") return DBItem.ActionWithDupl.AppendItems;

            Dish oldDish = (Dish)oldItem;
            Dish newDish = (Dish)newItem;
            string mess = "Блюдо с именем '" + newDish.Name + "' уже существует. Заменить это блюдо новым?\r\n";
            mess += "СУЩЕСТВУЮЩЕЕ БЛЮДО:\r\n\t'" + oldDish.FPath + "'\r\n\t[" + oldDish.ToString() + "]\r\n";
            mess += "НОВОЕ БЛЮДО:\r\n\t'" + newDish.FPath + "'\r\n\t[" + newDish.ToString() + "]";
            if (MessageBox.Show(mess, "Перемещение", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.No)
                return DBItem.ActionWithDupl.NotReplase;

            return DBItem.ActionWithDupl.Replace;
        }

        #endregion *** Drag And Drop ***************************************************************

        private void lv2_DragOver(object sender, DragEventArgs e)
        {
            //
        }

        private void lv1_DragOver(object sender, DragEventArgs e)
        {
            Point cp = lv1.PointToClient(new Point(e.X, e.Y));
            ListViewItem LastDragOverItem = DragOverItem;
            DragOverItem = lv1.GetItemAt(cp.X, cp.Y);
            if (DragOverItem != null)
            {
                if (DragOverItem.ImageIndex != 1) DragOverItem.ImageIndex = 1;
            }
            if (LastDragOverItem != null && (DragOverItem == null || DragOverItem.Index != LastDragOverItem.Index)) LastDragOverItem.ImageIndex = 0;

        }

    }
}
